package org.example.protocol;

import io.vertx.core.buffer.Buffer;
import org.example.constant.ProtocolConstant;
import org.example.enums.ProtocolMessageSerializerEnum;
import org.example.enums.ProtocolMessageTypeEnum;
import org.example.model.RpcRequest;
import org.example.model.RpcResponse;
import org.example.serializer.Serializer;
import org.example.serializer.SerializerFactory;
import org.example.serializer.SerializerFactorySpi;

import java.io.IOException;

/**
 * @description TODO
 * @author sats@jz
 * @date 2025年01月10日 16:11
 */
public class ProtocolMessageDecoder {


    public static ProtocolMessage<?> decoder(Buffer buffer) throws IOException {

        ProtocolMessage.Header header = new ProtocolMessage.Header();
        byte magic = buffer.getByte(0);
        // 校验魔数
        if (magic != ProtocolConstant.PROTOCOL_MAGIC) {
            throw new RuntimeException("消息非法，魔数错误");
        }
        header.setMagic(magic);
        header.setVersion(buffer.getByte(1));
        header.setSerializer(buffer.getByte(2));
        header.setMessageType(buffer.getByte(3));
        header.setStatus(buffer.getByte(4));
        header.setRequestId(buffer.getLong(5));
        int length = buffer.getInt(13);
        if(length < 0){
            throw new RuntimeException("消息非法，消息体长度为负");
        }

        if(buffer.length() < 17 + length){
            throw new RuntimeException("消息非法，消息体长度越界");
        }


        byte[] bodyBytes = buffer.getBytes(17, 17 + length);
        // 解析消息体
        ProtocolMessageSerializerEnum serializerEnum = ProtocolMessageSerializerEnum.getEnumByKey(header.getSerializer());
        if (serializerEnum == null) {
            throw  new RuntimeException("序列化协议不存在");
        }
        Serializer serializer = SerializerFactorySpi.getInstance(serializerEnum.getValue());
        ProtocolMessageTypeEnum messageTypeEnum = ProtocolMessageTypeEnum.getEnumByKey(header.getMessageType());
        if (messageTypeEnum == null){
            throw  new RuntimeException("消息类型不存在");
        }
        switch (messageTypeEnum) {
            case REQUEST:
                RpcRequest rpcRequest = serializer.deserialize(bodyBytes, RpcRequest.class);
                return new ProtocolMessage<>(header, rpcRequest);
            case RESPONSE:
                RpcResponse rpcResponse = serializer.deserialize(bodyBytes, RpcResponse.class);
                return new ProtocolMessage<>(header, rpcResponse);
            case HEART_BEAT:
            case OTHERS:
            default:
                throw new RuntimeException("暂不支持该消息类型");
        }

    }
}
